package com.dodo.blog.ui.util;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.logging.Logger;

/**
 * @author <a href="mailto:pohorelec@comvai.com">Jozef Pohorelec</a>
 */
public class ClosureCompiler
{
    private static Logger log = Logger.getLogger( ClosureCompiler.class.getName() );

    public static void main( String[] args ) throws Exception
    {
        String pathToXML = args[0];
        String outputPath = args[1];

        for ( GCC gcc : getFiles( pathToXML ) )
        {
            Runtime runtime = Runtime.getRuntime();
            String jsFile = gcc.getJavascriptName() + ".js";
            String output = outputPath + "/" + jsFile;
            String command = "java -jar compiler.jar" + gcc.getJs() + " --manage_closure_dependencies --compilation_level ADVANCED_OPTIMIZATIONS --js_output_file " + output;

            log.info( "Executing compilation for file: '" + jsFile );

            Process process = runtime.exec( command );
            try
            {
                log.info( new Scanner( process.getErrorStream() ).useDelimiter( "\\A" ).next() );
            }
            catch ( NoSuchElementException e )
            {
                // ignore
            }
        }
    }

    private static List<GCC> getFiles( String pathToXML ) throws ParserConfigurationException, IOException, SAXException
    {
        List<GCC> list = new ArrayList<GCC>();

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse( pathToXML );

        Element groups = ( Element ) document.getElementsByTagName( "groups" ).item( 0 );
        NodeList groupList = groups.getElementsByTagName( "group" );
        for ( int i = 0; i < groupList.getLength(); i++ )
        {
            GCC gcc = new GCC();

            Element group = ( Element ) groupList.item( i );
            gcc.setJavascriptName( group.getAttribute( "name" ) );

            // add common javascripts
            parseCommonJs( groups, gcc );

            // add custom javascripts
            NodeList jsList = group.getElementsByTagName( "js" );
            for ( int j = 0; j < jsList.getLength(); j++ )
            {
                Element js = ( Element ) jsList.item( j );
                gcc.addJs( js.getTextContent() );
            }

            list.add( gcc );
        }

        return list;
    }

    private static void parseCommonJs( Element groups, GCC gcc )
    {
        Element common = ( Element ) groups.getElementsByTagName( "common" ).item( 0 );
        NodeList commonJsList = common.getElementsByTagName( "js" );
        for ( int k = 0; k < commonJsList.getLength(); k++ )
        {
            Element commonJs = ( Element ) commonJsList.item( k );
            gcc.addJs( commonJs.getTextContent() );
        }
    }

    private static class GCC
    {
        private String javascriptName;

        private StringBuilder js = new StringBuilder();

        public void setJavascriptName( String javascriptName )
        {
            this.javascriptName = javascriptName;
        }

        public String getJavascriptName()
        {
            return javascriptName;
        }

        public String getJs()
        {
            return js.toString();
        }

        public void addJs( String js )
        {
            this.js.append( " --js " ).append( js );
        }
    }
}
